<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>微信语音聊天</title>
		<link rel="stylesheet" href="./css/toast.css" />
		<link rel="stylesheet" href="./css/chartVoice.css" />
		<style>

		</style>
	</head>
	<body>
		<!--语音- 通话中界面 -->
		<div class="voice-container" id="voiceCall">
			<div class="remote-avatar">
				<img src="https://via.placeholder.com/180/333/666" alt="被呼叫对方头像" class="avatar-image">
			</div>

			<div class="local-avatar">
				<img src="https://via.placeholder.com/80/555/888" alt="我的头像">
			</div>
			<!-- 当前用户通话-名字、时间 -->
			<div class="call-info">
				<div class="caller-name">张三</div>
				<div class="call-status time">00:05:23</div>
			</div>
			<!-- ?? -->
			<div class="voice-wave">
				<div class="wave-bar"></div>
				<div class="wave-bar"></div>
				<div class="wave-bar"></div>
				<div class="wave-bar"></div>
				<div class="wave-bar"></div>
			</div>
			<!-- 通话功能 -->
			<div class="control-buttons">
				<button class="control-button mute" id="muteBtn">
					<img class="fa" src="./images/microphone.svg" alt="" />
					<span>静音</span>
				</button>
				<button class="control-button speaker" id="speakerBtn">
					<img class="fa" src="./images/volume-off.svg" alt="" />
					<span>扬声器</span>
				</button>
				<button class="control-button end-call" id="endCallBtn">
					<img class="fa" src="./images/phone-slash.svg" alt="" />
					<span>挂断</span>
				</button>
			</div>
		</div>

		<!-- 语音-来电界面 -->
		<div id="incomingCall">
			<div class="incoming-call">
				<img src="https://via.placeholder.com/150/333/666" alt="头像" class="caller-avatar">
				<div class="caller-name">李四</div>
				<div class="call-status a1">语音通话邀请...</div>
				<div class="answer-buttons">
					<div class="decline-call" id="declineCallBtn">
						<img class="fa" src="./images/phone-slash.svg" alt="" />
					</div>
					<div class="accept-call" id="acceptCallBtn">
						<img class="fa" src="./images/phone.svg" alt="" />
					</div>
				</div>
			</div>
		</div>
		<!-- toast提示 -->
		<div id="toast" class="toast hide">
			<div class="toast-content">
				<p id="toastMessage"></p>
			</div>
		</div>
		<script type="text/javascript" src="./js/uni.webview.1.5.2.js"></script>
		<script src="./js/AgoraRTC_N-4.8.0.js"></script>
		<script>
			// 在初始化代码前加入
			window.addEventListener('unhandledrejection', (event) => {
			  if (event.reason?.message?.includes("Failed to execute 'getStats'")) {
			    event.preventDefault(); // 阻止控制台报错
			    console.warn("[AgorRTC 内部错误已忽略]", event.reason);
			  }
			});
			// 方案1：等待 UniApp 环境就绪事件
			document.addEventListener('UniAppJSBridgeReady', () => {
				console.log('UniAppJSBridgeReady:', ); // 处理接收到的消息
				// sendToUniApp('handeUp');
				document.addEventListener('DOMContentLoaded', function() {
					// 获取DOM元素
					const incomingCall = document.getElementById('incomingCall');
					const videoCall = document.getElementById('voiceCall');
					const acceptCallBtn = document.getElementById('acceptCallBtn');
					const declineCallBtn = document.getElementById('declineCallBtn');
					const endCallBtn = document.getElementById('endCallBtn');
					const muteBtn = document.getElementById('muteBtn');
					const speakerBtn = document.getElementById('speakerBtn');

					// 检查所有必需的DOM元素是否存在
					if (!incomingCall || !videoCall || !acceptCallBtn || !declineCallBtn || !endCallBtn || !muteBtn || !
						speakerBtn) {
						console.error('未能找到所有必需的DOM元素');
						return;
					}

					// 然后继续您的其余代码...
					const params = getUrlParams();
					console.log("params 参数:", params);

					let isSelf = false;
					isSelf = params.isSelf;

					// 其余代码...
				});
			});
			// 发送给外层信息
			function sendToUniApp(message) {
				console.log("向外层发送消息:",message);
				// 方法1：标准 UniApp 方式
				if (window.uni?.postMessage) {
					uni.postMessage({
						data: message
					}); // 注意必须是数组
					return;
				}

				// 方法2：URL Scheme 回退
				// try {
				//   location.href = `uniwebview://postMessage?data=${encodeURIComponent(JSON.stringify(message))}`;
				// } catch (e) {
				//   console.error('URL Scheme 失败:', e);
				// }

				// 方法3：通过 parent 通信（如果是 iframe 嵌套）
				if (window.parent !== window) {
					window.parent.postMessage({
						type: 'webview',
						data: message
					}, '*');
				}
			}
			// 工具函数：解析 URL 参数
			function getUrlParams() {
				const urlParams = new URLSearchParams(window.location.search);
				const paramsObject = {};
				urlParams.forEach((value, key) => {
					paramsObject[key] = value;
				});
				// console.log('paramsObject',paramsObject)
				return paramsObject; // 或者 return JSON.stringify(paramsObject); 如果你想要JSON字符串
			}
			const params = getUrlParams();
			console.log("params 参数:", params);

			let isSelf = false
			isSelf = params.isSelf
			if (isSelf == true) {
				document.getElementById('acceptCallBtn').style.display = 'none'
			} else {
				document.getElementById('acceptCallBtn').style.display = 'flex'
			}
			// 获取DOM元素
			const incomingCall = document.getElementById('incomingCall');
			const videoCall = document.getElementById('voiceCall');
			const acceptCallBtn = document.getElementById('acceptCallBtn');
			const declineCallBtn = document.getElementById('declineCallBtn');
			const endCallBtn = document.getElementById('endCallBtn');
			const channelInfo = JSON.parse(decodeURIComponent(params.channelInfo))
			const userInfo = JSON.parse(params.userInfo)
			const contactInfo = JSON.parse(params.contactInfo)
			console.log('房间信息--channelInfo-', channelInfo)
			console.log('userInfo-被呼叫人', userInfo)
			console.log('contactInfo-呼叫人', contactInfo)
			// 来电界面-赋值
			Array.from(document.getElementsByClassName('caller-name')).forEach(function(item) {//呼叫人-name
				item.innerText = contactInfo.contactName
				console.log('',item.innerText); // 直接打印或进行其他操作
			});
			Array.from(document.getElementsByClassName('caller-avatar')).forEach(function(item) {//呼叫人-头像
				item.src = contactInfo.contactAvatar
				console.log(item.src); // 直接打印或进行其他操作
			});
			// 通话中-赋值
			Array.from(document.getElementsByClassName('avatar-image')).forEach(function(item) {//呼叫人-头像
				item.src = contactInfo.contactAvatar
			});


			const userId = userInfo.id
			// 模拟来电铃声
			function playRingtone() {
				// 实际应用中这里可以播放铃声
				console.log("播放来电铃声...");
			}
			// 等待 UniApp JS Bridge 准备就绪
			// 接听电话
			acceptCallBtn.addEventListener('click', async function() {
				console.log('接听---语音');
				// 加入频道先
				joinChannel()
			});

			// 拒接电话
			declineCallBtn.addEventListener('click', function() {
				incomingCall.style.display = 'none';
				// 停止铃声
				console.log("停止铃声");
				console.log("已拒绝语音通话");
				const call_request = {
					callerId: "caller",
					status: false,
					timestamp: Date.now(),
					userId: userId,
					type: 'voice'
				}
				sendToUniApp(call_request);
				// 实际应用中这里可以跳转回聊天界面
			});

			// 挂断电话
			endCallBtn.addEventListener('click', function() {
				handeUp(userId)
			});

			// 静音按钮
			muteBtn.addEventListener('click', async function() {
				this.classList.toggle('active');
				console.log('localAudioTrack', localAudioTrack);
				// await localAudioTrack.setMuted(!isCurrentlyMuted); // 使用 await 确保操作完成
				if (this.classList.contains('active')) {
					// this.querySelector('i').className = 'fas fa-microphone-slash';
					this.querySelector('img').src = './images/microphone-slash.svg'
					localAudioTrack.setVolume(0);
					console.log("已静音");
				} else {
					// this.querySelector('i').className = 'fas fa-microphone';
					this.querySelector('img').src = './images/microphone.svg'
					const volume = localAudioTrack._volume
					localAudioTrack.setVolume(volume);
					console.log("取消静音");
				}
			});

			// 扬声器按钮
			speakerBtn.addEventListener('click', async function() {
				
				this.classList.toggle('active');
				if (this.classList.contains('active')) {
					// this.querySelector('i').className = 'fas fa-volume-up';
					this.querySelector('img').src = './images/volume-up.svg'
					console.log("扬声器已开启");
					localAudioTrack.setVolume(100);
				} else {
					// this.querySelector('i').className = 'fas fa-volume-off';
					this.querySelector('img').src = './images/volume-off.svg'
					console.log("扬声器已关闭");
					localAudioTrack.setVolume(50);
				}
			});
			// 用户挂断
			function handeUp(userUid) {
				videoCall.style.display = 'none';
				console.log("视频通话已结束");
				const call_request = {
					callerId: "handelUp",
					status: false,
					timestamp: Date.now(),
					userId: userUid,
					type: 'voice'
				}
				sendToUniApp(call_request);
				stopCallTimer()
				leaveChannel()
			}
			// 远程用户接受加入频道
			function accetp(userUid) {
				let call_request = {
					callerId: "caller",
					status: true,
					timestamp: Date.now(),
					userId: userUid,
					type: 'voice'
				}
				sendToUniApp(call_request);
			}
			// 开始通话计时器
			let callTimer = null;

			function startCallTimer() {
				let seconds = 0;
				const timerElement = document.querySelector('.call-status');

				callTimer = setInterval(function() {
					seconds++;
					const hours = Math.floor(seconds / 3600);
					const minutes = Math.floor((seconds % 3600) / 60);
					const secs = seconds % 60;

					timerElement.textContent =
						`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
				}, 1000);
			}
			// 停止通话计时
			function stopCallTimer() {
				if (callTimer) {
					clearInterval(callTimer);
					callTimer = null;
				}
			}
			// 页面加载时播放铃声
			window.addEventListener('load', function() {
				playRingtone();
			});

			// AgoraRTC 客户端和本地音频轨道变量
			let client = null;
			let localAudioTrack = null;

			// 加入频道
			async function joinChannel() {
				console.log('已接听-频道信息',this.channelInfo);
				const appId = channelInfo.appId.trim() || null;
				const channel = channelInfo.channel.trim() || null;
				const token = channelInfo.token.trim() || null;
				const userId = userInfo.id.trim() || null;

				if (!appId || !channel) {
					console.log("App ID 和频道名不能为空");
					return;
				}

				try {
					showToast('正在连接...')
					const devices = await AgoraRTC.getMicrophones();
					if (devices.length === 0) {
						console.log('未找到麦克风设备')
						handleJoinError(userId, '未找到麦克风设备')
						return;
					}
					console.log("正在初始化客户端...");
					AgoraRTC.setLogLevel(2); // 设置日志级别

					/**
					 * 初始化引擎，创建纯音频客户端
					 * 引入声网SDK,通过createClient()传递配置参数生成端口
					 * */
					client = AgoraRTC.createClient({
						mode: "rtc",
						codec: "vp8"
					});

					console.log("初始化成功", client);
					/**
					 *加入频道
					 * 通过join({channel_name,token,uid})加入频道
					 * appId 就是你在声网建立的应用ID。
					*/
					console.log("正在加入频道",{appId},{channel},{token},{userId});
					const uid = await client.join(appId, channel, token || null, userId);
					console.log('本地用户ID-被呼叫', uid);

					// 用户加入事件
					client.on("user-joined", async (user) => {
						console.log(`当前用户 ${user.uid} 加入了频道`);
						addUserToUI(user.uid); // 在UI上添加用户
						await publishAudio()
						// accetp(user.uid)
					});
					// 监听用户加入并发布音频流事件
					client.on("user-published", async (user, mediaType) => {
						if (mediaType === "audio") {
							await client.subscribe(user, mediaType);
							console.log(`远程用户 ${user.uid} 发布了音频流`);

							// 播放远程音频
							user.audioTrack.play();
							startCallTimer() //语音通话开始计时
							// 启用音频等级检测
							client.enableAudioVolumeIndicator();

							client.on("volume-indicator", (volumes) => {
								volumes.forEach((volume) => {
									if (volume.level > 5) { // level范围 0~9 // 更新UI显示对方正在说话
										// console.log(`用户 ${volume.uid} 正在说话`);
										updateRemoteUserSpeakingStatus(volume.uid, true);
									} else {
										// console.log(`用户 ${volume.uid} 没有说话`);
										updateRemoteUserSpeakingStatus(volume.uid, false);
									}
								});
							});
							user.audioTrack.on("mute", () => {
								// updateRemoteUserSpeakingStatus(user.uid, true);
								console.log(`用户 ${user.uid} 没有静音`);
							});
							user.audioTrack.on("unmute", () => {
								// updateRemoteUserSpeakingStatus(user.uid, false);
								console.log(`用户 ${user.uid} 已静音`);
							});
						}
					});

					// 监听用户取消发布音频流事件
					client.on("user-unpublished", (user, mediaType) => {
						if (mediaType === "audio") {
							console.log(`远程用户 ${user.uid} 取消了音频流`);
							// 监听到远程用户离开就自动挂断
							handeUp(user.uid)
							updateRemoteUserSpeakingStatus(user.uid, false);
						}
					});

					// 监听用户离开事件
					client.on("user-left", (user) => {
						console.log(`远程用户 ${user.uid} 已离开`);
						updateRemoteUserSpeakingStatus(user.uid, false);
						handeUp(user.uid)
					});

					// 网络质量检测
					client.on("network-quality", (stats) => {
						// console.log('network-quality',stats)
						// 确保 stats 存在再使用
						if (stats) updateNetworkStatus(stats);
					});
					// 自动发布音频流
					// await publishAudio();

				} catch (error) {
					console.log(`加入频道失败: ${error.message}`);
					console.error(error);
					handleJoinError(userId, '获取麦克风权限失败');
					stopCallTimer()
				}
			}

			// 发布本地音频流
			async function publishAudio() {
				console.log('加入频道之后-处理');
				if (!client) {
					console.log("请先加入频道");
					return;
				}

				try {
					console.log("正在获取麦克风权限...");

					// 创建本地音频轨道
					localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack({
						encoderConfig: "speech_standard", // 语音优化配置
						AEC: true, // 回声消除
						ANS: true // 降噪
					});

					// 监听本地音频音量变化
					// localAudioTrack.setVolume(100);
					localAudioTrack.on("volume-change", (volume) => {
						console.log('volume', volume)
						if (volume == 0) { //就静音了
							if (muteBtn.classList.contains('active')) {
								muteBtn.classList.remove('active');
							}
							// document.getElementsByName('muteBtn') = 'fas fa-microphone-slash';
						} else {
							muteBtn.classList.add('active');
						}
						// updateLocalSpeakingStatus(volume > 50);
					});
					localAudioTrack.on("track-ended", () => {
						console.error("音频轨道意外结束！");
					});
					// 发布本地音频轨道
					console.log("正在发布本地音频流...");
					await client.publish([localAudioTrack]);
					console.log("本地音频流已发布,本地用户-被呼叫用户" + userId);

				} catch (error) {
					console.log(`发布音频流失败: ${error.message}`);

					// 发生错误时关闭轨道
					if (localAudioTrack) {
						localAudioTrack.close();
						localAudioTrack = null;
					}

					handlePublishError(userId, '获取麦克风权限失败');
					stopCallTimer()
				}
			}

			// 取消发布本地音频流
			async function unpublishAudio() {
				if (!client) {
					console.log("客户端未初始化");
					return;
				}

				try {
					console.log("正在取消发布本地音频流...");

					if (localAudioTrack) {
						await client.unpublish([localAudioTrack]);
						localAudioTrack.close();
						localAudioTrack = null;
					}

					console.log("已取消发布本地音频流");

				} catch (error) {
					console.log(`取消发布失败: ${error.message}`);
					console.error(error);
				}
			}

			// 离开频道
			async function leaveChannel() {
				if (!client) {
					console.log("客户端未初始化");
					return;
				}
				try {
					console.log("开始挂断流程...");

					// 1. 先取消发布所有轨道
					if (localAudioTrack) {
						console.log("取消发布音频轨道...");
						// 停止发布本地音视频流
						await client.unpublish([localAudioTrack]);
						localAudioTrack.close();
						localAudioTrack = null;
					}

					// 2. 然后离开频道
					console.log("离开频道...");
					await client.leave();
					client = null;

					console.log("挂断流程完成");

					// 3. 更新UI状态
					// updateUIAfterHangUp();

				} catch (error) {
					console.error("挂断过程中出错:", error);
					// 即使出错也尝试强制清理
					forceCleanup();
					throw error;
				}
			}
			// 强制清理资源
			function forceCleanup() {
				if (localAudioTrack) {
					try {
						localAudioTrack.close();
					} catch (e) {
						console.warn("强制关闭音频轨道时出错:", e);
					}
					localAudioTrack = null;
				}

				if (client) {
					try {
						client.leave();
					} catch (e) {
						console.warn("强制离开频道时出错:", e);
					}
					client = null;
				}
			}

			function handleJoinError(userId, error) {
				// 处理加入频道错误
				const call_request = {
					callerId: "audioCall",
					status: false,
					timestamp: Date.now(),
					userId: userId,
					error: error
				}
				sendToUniApp(call_request);
			}

			function handlePublishError(userId, error) {
				// 处理发布音频错误
				const call_request = {
					callerId: "audioCall",
					status: false,
					timestamp: Date.now(),
					userId: userId,
					error: error
				}
				sendToUniApp(call_request);
			}
			// 获取可用的音频输出设备
			async function getSpeakerDevices() {
				try {
					const devices = await AgoraRTC.getPlaybackDevices(); // 获取所有音频输出设备
					if (devices.length === 0) {
						console.warn("没有可用的扬声器设备！");
						return [];
					}
					console.log("可用的扬声器设备:", devices);
					return devices;
				} catch (err) {
					console.error("获取扬声器设备失败:", err);
					return [];
				}
			}
			// UI更新函数
			function updateLocalSpeakingStatus(isSpeaking) {
				// 更新本地用户说话状态UI
				const localAvatar = document.querySelector('.local-avatar');
				if (isSpeaking) {
					localAvatar.classList.add('speaking');
				} else {
					localAvatar.classList.remove('speaking');
				}
			}

			function updateRemoteUserSpeakingStatus(uid, isSpeaking) {
				// 更新远程用户说话状态UI
				// 开始讲话
				const voiceWave = document.getElementsByClassName('voice-wave');
				// const remoteUserElement = document.getElementById(`remote-${uid}`);
				// console.log('voiceWave', voiceWave, isSpeaking)
				if (voiceWave) {
					if (isSpeaking) {
						voiceWave[0].style.display = 'flex'
						// remoteUserElement.classList.add('speaking');
					} else {
						voiceWave[0].style.display = 'none'
						// remoteUserElement.classList.remove('speaking');
					}
				}
			}

			// UI更新函数示例
			function addUserToUI(uid) {
				// 创建或更新UI元素显示用户
				Array.from(document.getElementsByClassName('local-avatar')).forEach(function(item) {
					item.src = userInfo.avatar
				});

				// 停止铃声
				// 开始计时器等操作
				incomingCall.style.display = 'none';
				videoCall.style.display = 'block';
				// const userElement = document.createElement("div");
				// userElement.id = `user-${uid}`;
				// userElement.innerHTML = `用户: ${uid}`;
				// document.getElementById("user-list").appendChild(userElement);
			}
			// 更新网络状态显示
			function updateNetworkStatus(stats) {
				let status = "网络良好";
				let color = "#34c759";

				// 下行网络质量
				if (stats.downlinkNetworkQuality > 4) {
					status = "网络较差";
					color = "#ff9500";
					showToast('网络较差')
				}
				if (stats.downlinkNetworkQuality > 6) {
					status = "网络非常差";
					color = "#ff3b30";
					showToast('网络非常差')
				}

				// networkStatus.textContent = status;
				// networkStatus.style.color = color;
			}
			// 提示框
			function showToast(message) {
				const toast = document.getElementById('toast');
				const toastMessage = document.getElementById('toastMessage');
				toastMessage.textContent = message;
				toast.classList.add('show');
				toast.classList.remove('hide');
				setTimeout(() => {
					toast.classList.remove('show');
					setTimeout(() => {
						toast.classList.add(
							'hide'); // Hide after animation completes to avoid flickering on quick show/hide actions.
					}, 300); // Ensures the transition completes before hiding to avoid visual glitches.
				}, 2000); // Display for 2 seconds then hide it.
			}
		</script>
	</body>
</html>